Skip to main content
  1. Posts/

Helix Theme Syncing with COSMIC

·4 mins

I recently switched to using a light theme during the day and a dark theme during the night. Everything works except for Helix since it does not support automatic theme switching. See the following issues for more details if you’re curious.

I’m running Arch Linux with the COSMIC desktop environment. COSMIC is configured to automatically switch to a light theme at sunrise and a dark theme at sunset. When sunset occurs I immediately see Chromium and Ghostty switch to a dark theme. Helix, however, remains on a light theme.

COSMIC doesn’t make use of gsettings like GNOME. Instead, it has its own settings files in /usr/share/cosmic and ~/.config/cosmic. One such file is ~/.config/cosmic/com.system76.CosmicTheme.Mode/v1/is_dark which returns true or false. Pretty convenient and self-explanatory. Let’s use that to automatically sync Helix’s theme with COSMIC.

Changing the Helix Theme #

I recently switched to Nushell so I decided to write a Nushell script to do the heavy lifting and try out some of its features. Here’s the final script that I saved to ~/bin/helix-theme-sync.nu.

#! /usr/bin/env nu

const helix_config = ($nu.home-path | path join ".config/helix/config.toml")

# Looks complex but it's not bad.
# \K      -> Discards what came before and keeps what follows.
# (?=...) -> A lookahead to ensure what matches isn't replaced.
const regex = '^theme\s+=\s+"\K\w+(?=".*)'

let is_dark = (open ~/.config/cosmic/com.system76.CosmicTheme.Mode/v1/is_dark | str trim | into bool)

# We specifically use `open --raw` with `str replace` to prevent Nushell from
# changing the format of the TOML file (e.g., don't remove extra spacing).
if $is_dark {
  open --raw $helix_config | str replace --regex $regex 'gruvbox' | save -f $helix_config
} else {
  open --raw $helix_config | str replace --regex $regex 'gruvbox_light' | save -f $helix_config
}

I commented this for readers so I’ll skip explaining it further. Ping me if it’s still unclear!

For the experienced Nushell people, yes I could have done something like the following instead, but I didn’t like that Nushell reformatted the TOML file.

const helix_config = ($nu.home-path | path join ".config/helix/config.toml")
open $helix_config | upsert theme 'gruvbox' | save -f $helix_config

Now I can run helix-theme-sync.nu and Helix will automatically use a light or dark theme depending on what COSMIC is using. It’s still a manual process though so let’s tackle that next.

Syncing the Helix Theme Automatically #

This was far easier than I anticipated after I asked Claude Code how I could better accomplish this.

I created a ~/.config/systemd/user/helix-theme-sync.service file to call my Nushell script and update the Helix theme. Nothing fancy here.

[Unit]
Description=Sync the Helix theme with COSMIC

[Service]
Type=oneshot
ExecStart=/usr/bin/env nu %h/bin/helix-theme-sync.nu

[Install]
WantedBy=default.target

The magic happens in the ~/.config/systemd/user/helix-theme-sync.path file. To be honest, I completely forgot about systemd .path unit files so I was happy when Claude Code reminded me of them.

[Unit]
Description=Sync the Helix theme with COSMIC

[Path]
PathModified=%h/.config/cosmic/com.system76.CosmicTheme.Mode/v1/is_dark

[Install]
WantedBy=default.target

The way it works is the helix-theme-sync.path unit file watches the specified PathModified file for changes. When a change is detected it will run the systemd .service file of the same name (e.g., helix-theme-sync.service). Super simple!

Now, I just needed to reload the systemd user unit files and enable and start them.

systemctl --user daemon-reload
systemctl --user enable --now helix-theme-sync.service
systemctl --user enable --now helix-theme-sync.path

Done! Now when I change my COSMIC theme my Helix theme automatically changes.

Questions #

The keen reader might be asking themselves some questions. Let’s cover them.

What happens when the system is powered off while using the dark theme and started up during a time when it should use the light theme?

Simple! The helix-theme-sync.service file contains the following configuration.

[Install]
WantedBy=default.target

This means the service will run once on boot since the default.target is, well, the default boot target. This will see the current COSMIC theme and update Helix appropriately.

Will the Helix theme change live if it’s running during the update?

Nope! This would require either relaunching Helix or running :config-reload. I’m fine with either of those.

Matthew Sanabria
Author
Matthew Sanabria
Matthew is an engineering leader known for using his breadth and depth of experience to add value in minimal context situations. In his spare time, Matthew spends time with his family, helps grow his wife’s chocolate business, works on home improvement projects, and reads technical resources to learn and tinker.